﻿using System;
using System.Net;
using System.Collections.Generic;
using System.IO;

namespace Sausage.Common.Pinyin
{
    /// <summary>
    /// 拼音字典
    /// </summary>
    /// <remarks>用于保存拼音单元信息。</remarks>
    /// <history>
    /// [zanezeng]               2010/05/27 15:41    创建
    /// </history>
    public sealed class PinyinDictionary
    {
        /// <summary>
        /// 从给定的二进制读取对象中加载拼音字典。
        /// </summary>
        /// <param name="binaryReader">包含拼音字典的二进制读取对象。</param>
        /// <returns>从给定的二进制读取对象中加载的拼音字典</returns>
        /// <remarks></remarks>
        /// <history>
        /// [zanezeng]               2010/05/27 16:03    创建
        /// </history>
        public static PinyinDictionary Load(BinaryReader binaryReader)
        {
            //创建拼音字典
            PinyinDictionary dictionary = new PinyinDictionary();

            //读取整数
            binaryReader.ReadInt32();

            //读取长度
            dictionary.Length = binaryReader.ReadInt16();

            //读取总数
            dictionary.Count = binaryReader.ReadInt16();

            //读取偏移值
            dictionary.m_Offset = binaryReader.ReadInt16();

            //读取保留值
            binaryReader.ReadBytes(dictionary.Reserved.Length);

            //创建拼音单元表
            dictionary.m_PinyinUnitTable = new List<PinyinUnit>();

            //循环读取拼音单元
            for (int i = 0; i < dictionary.Count; i++)
            {
                //读取拼音单元
                dictionary.m_PinyinUnitTable.Add(PinyinUnit.Load(binaryReader));
            }

            //读取结束掩码
            binaryReader.ReadInt16();

            //返回字典
            return dictionary;
        }

        /// <summary>
        /// 获得给定拼音对应的拼音单元
        /// </summary>
        /// <param name="pinyin">要获得拼音单元的拼音字符串。</param>
        /// <returns>给定拼音对应的拼音单元。</returns>
        /// <remarks></remarks>
        /// <history>
        /// [zanezeng]               2010/05/27 16:08    创建
        /// </history>
        public PinyinUnit GetPinYinUnit(string pinyin)
        {
            //检索拼音单元
            foreach (PinyinUnit unit in this.m_PinyinUnitTable)
            {
                //判断是否相同
                if (0 == string.Compare(pinyin, unit.Pinyin, StringComparison.CurrentCultureIgnoreCase))
                {
                    //返回拼音单元
                    return unit;
                }
            }

            //默认返回空引用
            return null;
        }

        /// <summary>
        /// 获得给定序号的拼音单元。
        /// </summary>
        /// <param name="index">要获得的拼音单元的序号。</param>
        /// <returns>给定序号的拼音单元。</returns>
        /// <remarks></remarks>
        /// <history>
        /// [zanezeng]               2010/05/27 16:09    创建
        /// </history>
        public PinyinUnit GetPinYinUnitByIndex(int index)
        {
            //判断是否越界
            if (index < 0 || index > this.m_PinyinUnitTable.Count - 1)
            {
                //如果越界，则返回空引用
                return null;
            }

            //返回拼音单元
            return this.m_PinyinUnitTable[index];
        }

        /// <summary>
        /// 获得给定拼音对应的拼音单元的序号。
        /// </summary>
        /// <param name="pinyin">要获得拼音单元序号的拼音字符串。</param>
        /// <returns>给定拼音对应的拼音单元的序号，如果不存在，则返回-1。</returns>
        /// <remarks></remarks>
        /// <history>
        /// [zanezeng]               2010/05/27 16:10    创建
        /// </history>
        public int GetPinYinUnitIndex(string pinyin)
        {
            //检索拼音单元
            for (int index = 0; index < this.m_PinyinUnitTable.Count; index++)
            {
                //获得拼音单元
                PinyinUnit unit = this.m_PinyinUnitTable[index];

                //判断是否相同
                if (0 == string.Compare(pinyin, unit.Pinyin, StringComparison.CurrentCultureIgnoreCase))
                {
                    //返回拼音单元
                    return index;
                }
            }

            //默认返回-1
            return -1;
        }

        /// <summary>
        /// 将拼音单元字典保存到给定的二进制写入对象中。
        /// </summary>
        /// <param name="binaryWriter">用于保存拼音单元字典的二进制写入对象。</param>
        /// <remarks></remarks>
        /// <history>
        /// [zanezeng]               2010/05/27 16:11    创建
        /// </history>
        public void Serialize(BinaryWriter binaryWriter)
        {
            //写入长度
            binaryWriter.Write(this.Length);

            //写入总数
            binaryWriter.Write(this.Count);

            //写入偏移值
            binaryWriter.Write(this.m_Offset);

            //写入保留值
            binaryWriter.Write(this.Reserved);

            //循环写入拼音单元
            for (int i = 0; i < this.Count; i++)
            {
                //写入拼音单元
                this.m_PinyinUnitTable[i].Save(binaryWriter);
            }

            //写入结束掩码
            binaryWriter.Write(this.m_EndMark);
        }

        #region ---Property

        /// <summary>
        /// 获得或者设置拼音单元的总数
        /// </summary>
        /// <value>拼音单元的总数</value>
        /// <remarks></remarks>
        /// <history>
        /// [zanezeng]               2010/05/27 16:05    创建
        /// </history>
        public short Count
        {
            get;
            set;
        }

        /// <summary>
        /// 结束掩码
        /// </summary>
        private readonly short m_EndMark = 32767;

        /// <summary>
        /// 获得或者设置长度
        /// </summary>
        /// <value>长度</value>
        /// <remarks></remarks>
        /// <history>
        /// [zanezeng]               2010/05/27 16:06    创建
        /// </history>
        public short Length
        {
            get;
            set;
        }

        /// <summary>
        /// 偏移值
        /// </summary>
        private short m_Offset;

        /// <summary>
        /// 拼音单元表
        /// </summary>
        private List<PinyinUnit> m_PinyinUnitTable;

        /// <summary>
        /// 保留值
        /// </summary>
        private readonly byte[] Reserved = new byte[8];

        #endregion
    }
}
